home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / MacPNG Library 1.02 / pngMacSrc 1.02 / PNG Library 0.80 / PNGWRITE.C < prev    next >
Text File  |  1996-05-29  |  14KB  |  464 lines

  1.  
  2. /* pngwrite.c - general routines to write a png file
  3.  
  4.    libpng 1.0 beta 2 - version 0.8
  5.    For conditions of distribution and use, see copyright notice in png.h
  6.    Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc.
  7.    August 20, 1995
  8.    */
  9.  
  10. /* get internal access to png.h */
  11. #define PNG_INTERNAL
  12. #include "png.h"
  13.  
  14. /* Writes all the png information.  This is the suggested way to use
  15.    the library.  If you have a new chunk to add, make a function to
  16.    write it, and put it in the correct location here.  If you want
  17.    the chunk written after the image data, put it in png_write_end().
  18.    I strongly encurage you to supply a PNG_INFO_ flag, and check
  19.    info->valid before writing the chunk, as that will keep the code
  20.    from breaking if you want to just write a plain png file.
  21.    If you have long comments, I suggest writing them in png_write_end(),
  22.    and compressing them. */
  23. void
  24. png_write_info(png_struct *png_ptr, png_info *info)
  25. {
  26.    png_write_sig(png_ptr); /* write PNG signature */
  27.    /* write IHDR information. */
  28.    png_write_IHDR(png_ptr, info->width, info->height, info->bit_depth,
  29.       info->color_type, info->compression_type, info->filter_type,
  30.       info->interlace_type);
  31.    /* the rest of these check to see if the valid field has the appropriate
  32.       flag set, and if it does, writes the chunk. */
  33. #if defined(PNG_WRITE_gAMA_SUPPORTED)
  34.    if (info->valid & PNG_INFO_gAMA)
  35.       png_write_gAMA(png_ptr, info->gamma);
  36. #endif
  37. #if defined(PNG_WRITE_sBIT_SUPPORTED)
  38.    if (info->valid & PNG_INFO_sBIT)
  39.       png_write_sBIT(png_ptr, &(info->sig_bit), info->color_type);
  40. #endif
  41. #if defined(PNG_WRITE_cHRM_SUPPORTED)
  42.    if (info->valid & PNG_INFO_cHRM)
  43.       png_write_cHRM(png_ptr,
  44.          info->x_white, info->y_white,
  45.          info->x_red, info->y_red,
  46.          info->x_green, info->y_green,
  47.          info->x_blue, info->y_blue);
  48. #endif
  49.    if (info->valid & PNG_INFO_PLTE)
  50.       png_write_PLTE(png_ptr, info->palette, info->num_palette);
  51. #if defined(PNG_WRITE_tRNS_SUPPORTED)
  52.    if (info->valid & PNG_INFO_tRNS)
  53.       png_write_tRNS(png_ptr, info->trans, &(info->trans_values),
  54.          info->num_trans, info->color_type);
  55. #endif
  56. #if defined(PNG_WRITE_bKGD_SUPPORTED)
  57.    if (info->valid & PNG_INFO_bKGD)
  58.       png_write_bKGD(png_ptr, &(info->background), info->color_type);
  59. #endif
  60. #if defined(PNG_WRITE_hIST_SUPPORTED)
  61.    if (info->valid & PNG_INFO_hIST)
  62.       png_write_hIST(png_ptr, info->hist, info->num_palette);
  63. #endif
  64. #if defined(PNG_WRITE_pHYs_SUPPORTED)
  65.    if (info->valid & PNG_INFO_pHYs)
  66.       png_write_pHYs(png_ptr, info->x_pixels_per_unit,
  67.          info->y_pixels_per_unit, info->phys_unit_type);
  68. #endif
  69. #if defined(PNG_WRITE_oFFs_SUPPORTED)
  70.    if (info->valid & PNG_INFO_oFFs)
  71.       png_write_oFFs(png_ptr, info->x_offset, info->y_offset,
  72.          info->offset_unit_type);
  73. #endif
  74. #if defined(PNG_WRITE_tIME_SUPPORTED)
  75.    if (info->valid & PNG_INFO_tIME)
  76.       png_write_tIME(png_ptr, &(info->mod_time));
  77.    /* Check to see if we need to write text chunks */
  78. #endif
  79. #if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
  80.    if (info->num_text)
  81.    {
  82.       int i; /* local counter */
  83.  
  84.       /* loop through the text chunks */
  85.       for (i = 0; i < info->num_text; i++)
  86.       {
  87.          /* if chunk is compressed */
  88.          if (info->text[i].compression >= 0)
  89.          {
  90. #if defined(PNG_WRITE_zTXt_SUPPORTED)
  91.             /* write compressed chunk */
  92.             png_write_zTXt(png_ptr, info->text[i].key,
  93.                info->text[i].text, info->text[i].text_length,
  94.                info->text[i].compression);
  95. #endif
  96.          }
  97.          else
  98.          {
  99. #if defined(PNG_WRITE_tEXt_SUPPORTED)
  100.             /* write uncompressed chunk */
  101.             png_write_tEXt(png_ptr, info->text[i].key,
  102.                info->text[i].text, info->text[i].text_length);
  103. #endif
  104.          }
  105.       }
  106.    }
  107. #endif
  108. }
  109.  
  110. /* writes the end of the png file.  If you don't want to write comments or
  111.    time information, you can pass NULL for info.  If you already wrote these
  112.    in png_write_info(), do not write them again here.  If you have long
  113.    comments, I suggest writing them here, and compressing them. */
  114. void
  115. png_write_end(png_struct *png_ptr, png_info *info)
  116. {
  117.    /* see if user wants us to write information chunks */
  118.    if (info)
  119.    {
  120. #if defined(PNG_WRITE_tIME_SUPPORTED)
  121.       /* check to see if user has supplied a time chunk */
  122.       if (info->valid & PNG_INFO_tIME)
  123.          png_write_tIME(png_ptr, &(info->mod_time));
  124. #endif
  125. #if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
  126.       /* check to see if we need to write comment chunks */
  127.       if (info->num_text)
  128.       {
  129.          int i; /* local index variable */
  130.  
  131.          /* loop through comment chunks */
  132.          for (i = 0; i < info->num_text; i++)
  133.          {
  134.             /* check to see if comment is to be compressed */
  135.             if (info->text[i].compression >= 0)
  136.             {
  137. #if defined(PNG_WRITE_zTXt_SUPPORTED)
  138.                /* write compressed chunk */
  139.                png_write_zTXt(png_ptr, info->text[i].key,
  140.                   info->text[i].text, info->text[i].text_length,
  141.                   info->text[i].compression);
  142. #endif
  143.             }
  144.             else
  145.             {
  146. #if defined(PNG_WRITE_tEXt_SUPPORTED)
  147.                /* write uncompressed chunk */
  148.                png_write_tEXt(png_ptr, info->text[i].key,
  149.                   info->text[i].text, info->text[i].text_length);
  150. #endif
  151.             }
  152.          }
  153.       }
  154. #endif
  155.    }
  156.    /* write end of png file */
  157.    png_write_IEND(png_ptr);
  158. }
  159.  
  160. #if defined(PNG_WRITE_tIME_SUPPORTED)
  161. void
  162. png_convert_from_struct_tm(png_time *ptime, struct tm *ttime)
  163. {
  164.    ptime->year = 1900 + ttime->tm_year;
  165.    ptime->month = ttime->tm_mon + 1;
  166.    ptime->day = ttime->tm_mday;
  167.    ptime->hour = ttime->tm_hour;
  168.    ptime->minute = ttime->tm_min;
  169.    ptime->second = ttime->tm_sec;
  170. }
  171.  
  172. void
  173. png_convert_from_time_t(png_time *ptime, time_t ttime)
  174. {
  175.    struct tm *tbuf;
  176.  
  177.    tbuf = gmtime(&ttime);
  178.    png_convert_from_struct_tm(ptime, tbuf);
  179. }
  180. #endif
  181.  
  182. /* initialize png structure, and allocate any memory needed */
  183. void
  184. png_write_init(png_struct *png_ptr)
  185. {
  186.    jmp_buf tmp_jmp; /* to save current jump buffer */
  187.  
  188.    /* save jump buffer */
  189.    memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
  190.    /* reset all variables to 0 */
  191.    memset(png_ptr, 0, sizeof (png_struct));
  192.    /* restore jump buffer */
  193.    memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
  194.  
  195.    /* initialize zbuf - compression buffer */
  196.    png_ptr->zbuf_size = PNG_ZBUF_SIZE;
  197.    png_ptr->zbuf = png_large_malloc(png_ptr, png_ptr->zbuf_size);
  198. }
  199.  
  200. /* write a few rows of image data.  If the image is interlaced,
  201.    either you will have to write the 7 sub images, or, if you
  202.    have called png_set_interlace_handling(), you will have to
  203.    "write" the image seven times */
  204. void
  205. png_write_rows(png_struct *png_ptr, png_byte **row,
  206.    png_uint_32 num_rows)
  207. {
  208.    png_uint_32 i; /* row counter */
  209.    png_byte **rp; /* row pointer */
  210.  
  211.    /* loop through the rows */
  212.    for (i = 0, rp = row; i < num_rows; i++, rp++)
  213.    {
  214.       png_write_row(png_ptr, *rp);
  215.    }
  216. }
  217.  
  218. /* write the image.  You only need to call this function once, even
  219.    if you are writing an interlaced image. */
  220. void
  221. png_write_image(png_struct *png_ptr, png_byte **image)
  222. {
  223.    png_uint_32 i; /* row index */
  224.    int pass, num_pass; /* pass variables */
  225.    png_byte **rp; /* points to current row */
  226.  
  227.    /* intialize interlace handling.  If image is not interlaced,
  228.       this will set pass to 1 */
  229.    num_pass = png_set_interlace_handling(png_ptr);
  230.    /* loop through passes */
  231.    for (pass = 0; pass < num_pass; pass++)
  232.    {
  233.       /* loop through image */
  234.       for (i = 0, rp = image; i < png_ptr->height; i++, rp++)
  235.       {
  236.          png_write_row(png_ptr, *rp);
  237.       }
  238.    }
  239. }
  240.  
  241. /* write a row of image data */
  242. void
  243. png_write_row(png_struct *png_ptr, png_byte *row)
  244. {
  245.    /* initialize transformations and other stuff if first time */
  246.    if (png_ptr->row_number == 0 && png_ptr->pass == 0)
  247.    {
  248.       png_write_start_row(png_ptr);
  249.    }
  250.  
  251. #if defined(PNG_WRITE_INTERLACING_SUPPORTED)
  252.    /* if interlaced and not interested in row, return */
  253.    if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
  254.    {
  255.       switch (png_ptr->pass)
  256.       {
  257.          case 0:
  258.             if (png_ptr->row_number & 7)
  259.             {
  260.                png_write_finish_row(png_ptr);
  261.                return;
  262.             }
  263.             break;
  264.          case 1:
  265.             if ((png_ptr->row_number & 7) || png_ptr->width < 5)
  266.             {
  267.                png_write_finish_row(png_ptr);
  268.                return;
  269.             }
  270.             break;
  271.          case 2:
  272.             if ((png_ptr->row_number & 7) != 4)
  273.             {
  274.                png_write_finish_row(png_ptr);
  275.                return;
  276.             }
  277.             break;
  278.          case 3:
  279.             if ((png_ptr->row_number & 3) || png_ptr->width < 3)
  280.             {
  281.                png_write_finish_row(png_ptr);
  282.                return;
  283.             }
  284.             break;
  285.          case 4:
  286.             if ((png_ptr->row_number & 3) != 2)
  287.             {
  288.                png_write_finish_row(png_ptr);
  289.                return;
  290.             }
  291.             break;
  292.          case 5:
  293.             if ((png_ptr->row_number & 1) || png_ptr->width < 2)
  294.             {
  295.                png_write_finish_row(png_ptr);
  296.                return;
  297.             }
  298.             break;
  299.          case 6:
  300.             if (!(png_ptr->row_number & 1))
  301.             {
  302.                png_write_finish_row(png_ptr);
  303.                return;
  304.             }
  305.             break;
  306.       }
  307.    }
  308. #endif
  309.  
  310.    /* set up row info for transformations */
  311.    png_ptr->row_info.color_type = png_ptr->color_type;
  312.    png_ptr->row_info.width = png_ptr->usr_width;
  313.    png_ptr->row_info.channels = png_ptr->usr_channels;
  314.    png_ptr->row_info.bit_depth = png_ptr->usr_bit_depth;
  315.    png_ptr->row_info.pixel_depth = png_ptr->row_info.bit_depth *
  316.       png_ptr->row_info.channels;
  317.    png_ptr->row_info.rowbytes = ((png_ptr->row_info.width *
  318.       (png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3);
  319.  
  320.    /* copy users row into buffer, leaving room for filter byte */
  321.    memcpy(png_ptr->row_buf + 1, row, (png_size_t)png_ptr->row_info.rowbytes);
  322.  
  323. #if defined(PNG_WRITE_INTERLACING_SUPPORTED)
  324.    /* handle interlacing */
  325.    if (png_ptr->interlaced && png_ptr->pass < 6 &&
  326.       (png_ptr->transformations & PNG_INTERLACE))
  327.    {
  328.       png_do_write_interlace(&(png_ptr->row_info),
  329.          png_ptr->row_buf + 1, png_ptr->pass);
  330.       /* this should always get caught above, but still ... */
  331.       if (!(png_ptr->row_info.width))
  332.       {
  333.          png_write_finish_row(png_ptr);
  334.          return;
  335.       }
  336.    }
  337. #endif
  338.  
  339.    /* handle other transformations */
  340.    if (png_ptr->transformations)
  341.       png_do_write_transformations(png_ptr);
  342.  
  343.    /* filter rows that have been proved to help */
  344.    if (png_ptr->do_filter)
  345.    {
  346.       /* save row to previous row */
  347.       memcpy(png_ptr->save_row, png_ptr->row_buf,
  348.          (png_size_t)png_ptr->row_info.rowbytes + 1);
  349.  
  350.       /* filter row */
  351.       png_write_filter_row(&(png_ptr->row_info), png_ptr->row_buf,
  352.          png_ptr->prev_row);
  353.  
  354.       /* trade saved pointer and prev pointer so next row references are correctly */
  355.       { /* scope limiter */
  356.          png_byte *tptr;
  357.  
  358.          tptr = png_ptr->prev_row;
  359.          png_ptr->prev_row = png_ptr->save_row;
  360.          png_ptr->save_row = tptr;
  361.       }
  362.    }
  363.    else
  364.       /* set filter row to "none" */
  365.       png_ptr->row_buf[0] = 0;
  366.  
  367.    /* set up the zlib input buffer */
  368.    png_ptr->zstream->next_in = png_ptr->row_buf;
  369.    png_ptr->zstream->avail_in = (uInt)png_ptr->row_info.rowbytes + 1;
  370.  
  371.    /* repeat until we have compressed all the data */
  372.    do
  373.    {
  374.       int ret; /* return of zlib */
  375.  
  376.       /* compress the data */
  377.       ret = deflate(png_ptr->zstream, Z_NO_FLUSH);
  378.       /* check for compression errors */
  379.       if (ret != Z_OK)
  380.       {
  381.          if (png_ptr->zstream->msg)
  382.             png_error(png_ptr, png_ptr->zstream->msg);
  383.          else
  384.             png_error(png_ptr, "zlib error");
  385.       }
  386.  
  387.       /* see if it is time to write another IDAT */
  388.       if (!png_ptr->zstream->avail_out)
  389.       {
  390.          /* write the IDAT and reset the zlib output buffer */
  391.          png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
  392.          png_ptr->zstream->next_out = png_ptr->zbuf;
  393.          png_ptr->zstream->avail_out = (uInt)png_ptr->zbuf_size;
  394.       }
  395.    /* repeat until all data has been compressed */
  396.    } while (png_ptr->zstream->avail_in);
  397.  
  398.    /* finish row - updates counters and flushes zlib if last row */
  399.    png_write_finish_row(png_ptr);
  400. }
  401.  
  402. /* free any memory used in png struct */
  403. void
  404. png_write_destroy(png_struct *png_ptr)
  405. {
  406.    jmp_buf tmp_jmp; /* save jump buffer */
  407.  
  408.    /* free any memory zlib uses */
  409.    deflateEnd(png_ptr->zstream);
  410.    /* free our memory.  png_free checks NULL for us. */
  411.    png_large_free(png_ptr, png_ptr->zbuf);
  412.    png_large_free(png_ptr, png_ptr->row_buf);
  413.    png_large_free(png_ptr, png_ptr->prev_row);
  414.    png_large_free(png_ptr, png_ptr->save_row);
  415.    /* reset structure */
  416.    memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
  417.    memset(png_ptr, 0, sizeof (png_struct));
  418.    memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
  419. }
  420.  
  421. void
  422. png_set_filtering(png_struct *png_ptr, int filter)
  423. {
  424.    png_ptr->do_custom_filter = 1;
  425.    png_ptr->do_filter = filter;
  426. }
  427.  
  428. void
  429. png_set_compression_level(png_struct *png_ptr, int level)
  430. {
  431.    png_ptr->zlib_custom_level = 1;
  432.    png_ptr->zlib_level = level;
  433. }
  434.  
  435. void
  436. png_set_compression_mem_level(png_struct *png_ptr, int mem_level)
  437. {
  438.    png_ptr->zlib_custom_mem_level = 1;
  439.    png_ptr->zlib_mem_level = mem_level;
  440. }
  441.  
  442. void
  443. png_set_compression_strategy(png_struct *png_ptr, int strategy)
  444. {
  445.    png_ptr->zlib_custom_strategy = 1;
  446.    png_ptr->zlib_strategy = strategy;
  447. }
  448.  
  449. void
  450. png_set_compression_window_bits(png_struct *png_ptr, int window_bits)
  451. {
  452.    png_ptr->zlib_custom_window_bits = 1;
  453.    png_ptr->zlib_window_bits = window_bits;
  454. }
  455.  
  456. void
  457. png_set_compression_method(png_struct *png_ptr, int method)
  458. {
  459.    png_ptr->zlib_custom_method = 1;
  460.    png_ptr->zlib_method = method;
  461. }
  462.  
  463.  
  464.